You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two follow-ups on the spiceai-54-vortex-0.85.0 re-cut (spiceai/spiceai#13570 Vortex pre-upgrade):
Arrow Map alias: confirmed superseded, not re-ported
840e746a9/3e7fa40d3 (the List<Struct<key,value>> alias restoration, spiceai/spiceai#13524) don't apply — upstream replaced the whole mechanism with a native Map array/dtype (vortex-array/src/dtype/map.rs, vortex-array/src/arrays/map/). Ran cargo test -p vortex-arrow --lib map on this branch: 17 tests pass, including the exact nested-extension-type scenario the old patch fixed (map_roundtrip_preserves_nested_uuid_fields). Upstream's own coverage here is broader than what Spice shipped. SPICE_PATCHES.md updated to reflect this as dropped-with-evidence rather than open work.
7e5b08151 doesn't cherry-pick — CastReduce::cast moved from fn cast(array: &ExtensionArray, ...) to fn cast(array: ArrayView<'_, Extension>, ...), and the "different extension type" branch now delegates eagerly to the storage array's generic cast instead of falling through to a specialized handler.
Confirmed the regression before porting: casting Date(Days) to Timestamp(Nanoseconds) on this branch currently fails with No CastKernel to cast canonical array vortex.primitive from i32 to vortex.timestamp[ns](i64). Without this, a pushed-down CAST(date_col AS TIMESTAMP) fails the scan outright (the array half of spiceai/spiceai#13624).
Ported both of the original tests (cast_date_days_to_timestamp_nanoseconds, cast_date_days_to_timestamp_seconds_nullable) unchanged in behavior; all 10 extension-cast tests pass, including the 8 pre-existing ones.
Part of the larger Vortex 0.79.0 -> 0.85.0 re-cut; still DataFusion 54 / Arrow 58.3.
…able
Traced through vortex-arrow's current Map handling instead of trusting the
merge-conflict shape: upstream 0.85.0 replaced the List<Struct<key,value>>
alias entirely with a native Map array/dtype (vortex-array/src/dtype/map.rs,
vortex-array/src/arrays/map/), and both the import and export paths already
recurse into map key/value fields for extension metadata the way Spice's
3e7fa40 did.
Ran the vortex-arrow map test suite on this branch (17 passing, including the
exact nested-extension-type scenario 3e7fa40 fixed) rather than asserting
this from the diff alone. Moves row 14 from "needs re-porting" to "dropped"
with that run as evidence.
…o 0.85.0
Ported forward from spiceai-54 (7e5b081), which doesn't apply as a
cherry-pick: CastReduce::cast moved from `fn cast(array: &ExtensionArray, ...)`
to `fn cast(array: ArrayView<'_, Extension>, ...)`, and the "different
extension type" branch now eagerly delegates to the storage array's generic
cast instead of falling through.
Confirmed the regression is real before porting, not assumed: casting a
Date(Days) array to Timestamp(Nanoseconds) on this branch failed with "No
CastKernel to cast canonical array vortex.primitive from i32 to
vortex.timestamp[ns](i64)" (see the removed probe in this file's history).
Without this patch a pushed-down `CAST(date_col AS TIMESTAMP)` fails the scan
outright (spiceai/spiceai#13624's array half).
Validity resolution needed its own adaptation: PrimitiveArray::validity_mask()
no longer exists (validity may now be lazy and needs an ExecutionCtx to
resolve), so this uses `legacy_session()` -- the crate's own sanctioned shim
for "code paths that cannot yet thread an explicit session through" -- the
same pattern Validity::is_valid/is_null already use.
Carries forward both of the original patch's tests unchanged in behavior,
confirmed passing against 0.85.0: cast_date_days_to_timestamp_nanoseconds and
cast_date_days_to_timestamp_seconds_nullable, plus all 8 pre-existing
extension-cast tests still pass.
…ys to timestamps instead of re-labelling (#75, #78, #93)
Re-ports two related fork patch families from spiceai-54 to 0.85.0 as fresh
implementations rather than cherry-picks, since neither applies: both touch
functions upstream restructured, and the second depends on the first already
being in place (resolve_timezone) to even compile against.
Fixed-offset timezone resolution (#75, #78): Arrow allows a timestamp's
timezone to be an IANA name or a fixed offset (+00:00), but jiff only
resolves IANA names, so any offset-form timezone aborted the process via
`.vortex_expect("unknown timezone")` -- in scalar validation, Display
rendering, and TemporalMetadata::to_jiff. Ports the fork's resolve_timezone
(new file, 38 passing tests carried over verbatim) and threads it through
all three sites, plus Scalar::try_extension_ref (a fallible counterpart to
the panicking extension_ref) through the three call sites that built
extension scalars infallibly on a read path (min/max aggregation, scalar_at,
the constant-folding reduce rule) and DateTimeParts::scalar_at.
Date -> timestamp conversion (#93, spiceai/spiceai#13624): Scalar::cast sent
any cast targeting an extension type through the target's storage type and
re-labelled the result, discarding what the source meant -- vortex.date and
vortex.timestamp both count from the epoch but in different units. A scan
falsifies `cast(col as timestamp) > lit` into `cast(max(col) as timestamp)
<= lit` and casts a file's statistic scalar to decide whether to read it at
all, so this silently pruned files whose rows would have matched. Ports
DateToTimestamp (new file, shared by both the array CastKernel and the
scalar cast so the two cannot disagree about which files/rows to keep) and
Timestamp::storage_range, replacing Jiff Span-based validation whose limits
are not a timestamp's at either end (span floor is one nanosecond above
i64::MIN, which a real timestamp[ns] column holds).
This supersedes a98a78c's array-only port on this branch: that port used
legacy_session() as a workaround for CastReduce's missing ExecutionCtx.
Discovered from an untracked later Spice commit that this fork's own answer
was to split into CastReduce (buffer-free restructuring) and a proper
CastKernel (which does get a real ctx) instead -- the same split this commit
uses, requiring an explicit `register_execute_parent_kernel(Cast.id(),
Extension, ...)` that has no upstream equivalent (Extension had no Cast
kernel at 0.85.0 at all, only the reduce path).
Verified: cargo test -p vortex-array -p vortex-datetime-parts --lib: 3428 +
72 passed, 0 failed. cargo check across vortex-array, vortex-arrow,
vortex-layout, vortex-file, vortex-io, vortex-utils, vortex-duckdb: clean,
zero warnings.
Not ported: the DuckDB TIMESTAMP_TZ dtype/scalar conversion's is_utc_timezone
gate (vortex-duckdb/src/convert/{dtype,scalar}.rs) -- vortex-duckdb is not a
crate Spice's Cargo.toml consumes, directly or transitively, so this is fork
hygiene rather than something Spice's re-pin needs. Left for a follow-up.
Moves rows 4, 7, 15, 16 from "needs re-porting" to a new applied section,
each with the commit and the test command that verified it, and notes that
the earlier a98a78c array-cast port is superseded rather than left as a
separate row.
…e call site
vortex-file/src/writer.rs's array-context construction was rewritten to call
the lock-free, Vec-returning session.enabled_component_ids(...) once instead
of the SessionGuard-returning session.arrays() twice in one statement -- the
exact pattern the original patch existed to prevent. Swept every remaining
session.arrays() call site across the crates Spice consumes; none re-invoke
it within a live guard's scope. No code change needed; moves row 6 from
"needs re-porting" to "dropped" with that sweep as evidence.
…ude it in PRUNING_STATS
Re-ports a9ef29d from spiceai-54: this fork's own ledger only tracked the
vendored, out-of-scope half of the original patch (vortex-datafusion), never
noticing this core-crate half existed. Confirmed it doesn't exist at 0.85.0
independently of the aggregate-fn redesign that moved computation of the
stat itself into a new AggregateFnVTable module -- that redesign changes how
the value is computed per array type, not whether it survives PRUNING_STATS
or a dict take, so this is still needed on top of it.
Without PRUNING_STATS including it, the stat isn't guaranteed to be computed
at write time. Without take.rs propagating it (alongside Min/Max/IsConstant,
which already were), a Dict-encoded column's byte-size statistic silently
disappears after any take/filter, and the optimizer mis-sizes joins built
over what remains -- a planning regression, not a correctness one, but a
silent one either way.
Added two tests (none existed for propagate_take_stats before): one
confirming the new stat carries forward inexactly, one confirming
IsConstant's existing inexact-propagation path (added by the same original
patch) still fires correctly when an index is null and the exact path above
it doesn't apply.
Verified: cargo test -p vortex-array --lib: 3430 passed (up from 3428), 0
failed. cargo check across vortex-array, vortex-arrow, vortex-layout,
vortex-file, vortex-io, vortex-utils, vortex-datetime-parts: clean.
Moves row 10's real fix from "needs re-porting" to the applied section with
its commit and the new tests that verify it, and notes explicitly that the
AggregateFnVTable redesign doesn't subsume it -- it changes computation, not
propagation or inclusion in PRUNING_STATS.
Read the full commit sequence rather than titles alone: the one non-perf
commit in the Sept-11 series (a panic fix in an extension list_contains
kernel) is itself deleted three commits later the same day, when the
extension-specific kernel it patched is replaced by generic-probe handling
-- matching 0.85.0, which never had that kernel. Not independently
reproduced against 0.85.0, so this is a reading, not a run, but the series
is not a live-bug row regardless: reframed from "needs its own audit" to "a
real but sizeable performance feature port against a since-rewritten
944-line file," deprioritized below the smaller items for that reason.
Also confirmed ab4f0b1 is moot (the file it touches doesn't exist at
0.85.0, the function it restores isn't referenced anywhere) and flagged
ccaa556's actual scope: it touches the central ExecutionCtx hot path, not
a leaf file, so it carries more blast radius than the other open items here.
Delegating the hour bound to Jiff accepts offsets through ±25:59:59, whereas Arrow-rs parses fixed offsets with chrono::FixedOffset, which rejects offsets of 24 hours or more. Consequently +25:00 is accepted here as an Arrow timezone and can enter timestamp metadata even though Arrow rejects it. Explicitly cap the hour component at 23.
…xpression
dafa096 (cherry-picked earlier on this branch as "Fix flat reader subrange
decode reuse") added a #[cfg(test)] module using APIs from spiceai-54's
2026-06-25 state: an undefined SESSION static (should be new_session()), an
ArrayContext passed without the .into() 0.85.0's write_stream signature
needs, and six call sites passing a raw Expression where LayoutReader's
filter_evaluation/projection_evaluation now require &BoundExpression
(upstream's "propagate bound expressions through layouts", vortex-data#9126).
This went undetected because the earlier verification pass ran `cargo check`
without --tests, so the test module's compile errors never surfaced --
surfaced only now while adding cargo check --tests coverage for a different
patch. Fixed by binding each expression once per branch with the same
`.bind(reader.dtype())` pattern the file's own flat_identity test already
used.
Verified: cargo test -p vortex-layout --lib layouts::flat::reader -- 9
passed, 0 failed. This is the first real test run of dafa096's actual
fix (segment-request coalescing across regressed query patterns), not
just a compile check.
…ts from host parallelism (#87)
Re-ports 4e2d626 from spiceai-54. Confirmed live at 0.85.0 before porting
(not assumed): ScanBuilder::with_concurrency's setting was multiplied by
get_available_parallelism() at two sites (scan_builder.rs, repeated_scan.rs),
so with_concurrency(1) still ran one split per worker thread rather than
serially -- a caller sizing a memory reservation against the configured
number under-reserves by the host's core count. MultiLayoutDataSource's
deferred-file-open concurrency had the same defect one level worse: it used
get_available_parallelism() as the value directly, so file-open width scaled
with the node under a cgroup CPU quota narrower than the machine, the same
class of bug crates/cpu-budget exists to prevent elsewhere.
Introduces SplitConcurrency (PerWorker/Absolute) with one effective() that
resolves either into a width, so a caller reading the setting and the scan
honoring it cannot disagree about what it meant. with_absolute_concurrency
is new; with_concurrency keeps its existing per-worker meaning.
MultiLayoutDataSource's deferred-open default is now the fixed
DEFAULT_CONCURRENCY (8), not the host's core count.
The bound only holds if split construction is lazy under it: constructing a
split task registers its reads with the I/O system, so building every task
up-front (the previous LazyScanState::Preparing / RepeatedScan::execute
path) let with_absolute_concurrency(1) still register every split's reads
before the first one was polled. RepeatedScan::execute now delegates to a
new split_tasks() lazy iterator that RepeatedScan::execute_stream buffers by
the configured concurrency, and ScanBuilder::into_stream only runs `prepare`
on the CPU pool before streaming through the same lazy path rather than
collecting every task first. execute()/build() are unchanged in meaning
(unbounded by the setting) and now say so in their docs.
Ported the two regression tests from the original patch (previously none
existed for this): both count registered splits via a new SplitProbe/
ProbeLayoutReader test harness in scan/test.rs and assert the high-water
mark equals the configured concurrency, covering absolute concurrency 1 and
3, ordered and unordered, at both the RepeatedScan and ScanBuilder layers.
Verified: cargo test -p vortex-layout --lib: 255 passed (up from 249), 0
failed -- including all 6 new/changed test cases. cargo test -p vortex-file
--lib: 139 passed, 0 failed (downstream consumer of the scan path). cargo
check --tests across vortex-array, vortex-arrow, vortex-layout, vortex-file,
vortex-io, vortex-utils, vortex-datetime-parts: clean, zero warnings.
Not ported: the vortex-file import-reordering hunks in this original commit
(driver.rs, request.rs, segments/source.rs) are pure rustfmt churn already
reflected in 0.85.0's own ordering; nothing to apply.
vortex-layout/src/scan/split_by.rs at 0.85.0 already carries 26b274c's
subdivide_large_spans function and all 5 of its unit tests, byte-for-byte
identical apart from unrelated test-helper API drift -- landed via upstream
commit 9d3aafb, which the row's own "Possibly upstream" guess had already
flagged as a candidate origin. vortex-file's end-to-end test is present too.
Ran both test suites rather than trusting the diff match alone. Moves the
row from "needs re-porting" to "dropped".
This sequential loop calls Mask::value(i) for every row, which recomputes the byte/bit offset each time. Mask::iter() is explicitly provided for sequential scans and advances one cursor, avoiding that per-element overhead in this full-array cast hot loop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two follow-ups on the
spiceai-54-vortex-0.85.0re-cut (spiceai/spiceai#13570 Vortex pre-upgrade):Arrow Map alias: confirmed superseded, not re-ported
840e746a9/3e7fa40d3(theList<Struct<key,value>>alias restoration, spiceai/spiceai#13524) don't apply — upstream replaced the whole mechanism with a nativeMaparray/dtype (vortex-array/src/dtype/map.rs,vortex-array/src/arrays/map/). Rancargo test -p vortex-arrow --lib mapon this branch: 17 tests pass, including the exact nested-extension-type scenario the old patch fixed (map_roundtrip_preserves_nested_uuid_fields). Upstream's own coverage here is broader than what Spice shipped.SPICE_PATCHES.mdupdated to reflect this as dropped-with-evidence rather than open work.Re-port:
vortex.date->vortex.timestampextension casts (#28)7e5b08151doesn't cherry-pick —CastReduce::castmoved fromfn cast(array: &ExtensionArray, ...)tofn cast(array: ArrayView<'_, Extension>, ...), and the "different extension type" branch now delegates eagerly to the storage array's generic cast instead of falling through to a specialized handler.Confirmed the regression before porting: casting
Date(Days)toTimestamp(Nanoseconds)on this branch currently fails withNo CastKernel to cast canonical array vortex.primitive from i32 to vortex.timestamp[ns](i64). Without this, a pushed-downCAST(date_col AS TIMESTAMP)fails the scan outright (the array half of spiceai/spiceai#13624).Ported both of the original tests (
cast_date_days_to_timestamp_nanoseconds,cast_date_days_to_timestamp_seconds_nullable) unchanged in behavior; all 10 extension-cast tests pass, including the 8 pre-existing ones.Part of the larger Vortex 0.79.0 -> 0.85.0 re-cut; still DataFusion 54 / Arrow 58.3.